package net.wzyjerry.springboot.demo.controller;

import net.wzyjerry.springboot.demo.SpringBootDemoApplication;
import net.wzyjerry.springboot.demo.model.Value;
import net.wzyjerry.springboot.demo.service.ValueService;
import net.wzyjerry.springboot.demo.viewModel.ValueViewModel;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

/**
 * Created by WzyJerry on 2017/10/21.
 * Value Controller
 */
@Controller
public class ValueController {

    /**
     * Value service
     */
    private ValueService valueService;

    /**
     * Settings
     */
    private SpringBootDemoApplication.Settings settings;

    /**
     * Construction of value controller
     *
     * @param valueService DI of value service
     * @param settings     DI of settings
     */
    public ValueController(ValueService valueService,
                           SpringBootDemoApplication.Settings settings) {
        this.valueService = valueService;
        this.settings = settings;
    }

    private Integer GetIndex(Integer id) {
        return (valueService.GetPosition(id) - 1) / settings.getPageSize() + 1;
    }

    private Integer GetDeleteIndex(Integer id) {
        Integer position = valueService.GetPosition(id);
        if (position <= settings.getPageSize()) {
            return 1;
        }
        if (position % settings.getPageSize() == 1) {
            return GetIndex(id) - 1;
        }
        return GetIndex(id);
    }

    @RequestMapping(value = {"/value/{index}", "/value/index/{index}"})
    public ModelAndView Index(@PathVariable Integer index) {
        ModelAndView modelAndView = new ModelAndView("value/index");
        Page<Value> page = valueService.Page(index);
        Integer totalPages = page.getTotalPages();
        if (totalPages.equals(0)) totalPages++;
        if (index > totalPages) {
            ModelAndView notFound = new ModelAndView("shared/404");
            notFound.addObject("errorMessage", "Index exceeded.");
            return notFound;
        }
        modelAndView.addObject("values", page);
        modelAndView.addObject("index", index);
        Integer start = index - 5 <= 1 ? 1 : index - 5;
        Integer end = start + 9 >= totalPages ? totalPages : start + 9;
        start = end - 9 <= 1 ? 1 : end - 9;
        modelAndView.addObject("start", start);
        modelAndView.addObject("end", end);
        modelAndView.addObject("totalPages", totalPages);
        return modelAndView;
    }

    @RequestMapping(value = "/value/create")
    public ModelAndView Create(@ModelAttribute("model") ValueViewModel model) {
        return new ModelAndView("value/create");
    }

    @RequestMapping(value = "/value/create", method = RequestMethod.POST)
    public ModelAndView Create(@Validated @ModelAttribute("model") ValueViewModel model, BindingResult result) {
        ModelAndView modelAndView = new ModelAndView("value/create");
        if (result.hasErrors()) {
            return modelAndView;
        }
        Value value = new Value();
        value.setKey(model.getKey());
        value.setValue(model.getValue());
        valueService.Create(value);
        modelAndView.setViewName("redirect:/value/index/" + GetIndex(value.getId()));
        return modelAndView;
    }

    @RequestMapping(value = "/value/update/{id}")
    public ModelAndView Update(@PathVariable Integer id, @ModelAttribute("model") ValueViewModel model) {
        ModelAndView modelAndView = new ModelAndView("value/update");
        Value value = valueService.Retrieve(id);
        model.setKey(value.getKey());
        model.setValue(value.getValue());
        return modelAndView;
    }

    @RequestMapping(value = "/value/update/{id}", method = RequestMethod.POST)
    public ModelAndView Update(@PathVariable Integer id, @Validated @ModelAttribute("model") ValueViewModel model, BindingResult result) {
        ModelAndView modelAndView = new ModelAndView("value/update");
        if (result.hasErrors()) {
            return modelAndView;
        }
        Value value = new Value();
        value.setId(id);
        value.setKey(model.getKey());
        value.setValue(model.getValue());
        valueService.Update(value);
        modelAndView.setViewName("redirect:/value/index/" + GetIndex(id));
        return modelAndView;
    }

    @RequestMapping(value = "/value/retrieve/{id}")
    public ModelAndView Retrieve(@PathVariable Integer id, @ModelAttribute("model") ValueViewModel model) {
        ModelAndView modelAndView = new ModelAndView("value/retrieve");
        Value value = valueService.Retrieve(id);
        model.setKey(value.getKey());
        model.setValue(value.getValue());
        return modelAndView;
    }

    @RequestMapping(value = "/value/delete", method = RequestMethod.POST)
    public ModelAndView Delete(Integer id) {
        ModelAndView modelAndView = new ModelAndView("redirect:/value/index/" + GetDeleteIndex(id));
        valueService.Delete(id);
        return modelAndView;
    }
}
